package com.example.chatroom.api;

import com.example.chatroom.component.OnlineUserManager;
import com.example.chatroom.model.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

@Component
public class WebSocketAPI extends TextWebSocketHandler {
    @Autowired
    private FriendReqMapper friendReqMapper;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MessageSessionMapper messageSessionMapper;

    @Autowired
    private MessageMapper messageMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("[WebSocketAPI] 连接成功");
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            return;
        }

        // 存入键值对
        onlineUserManager.online(user.getUserId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("[WebSocketAPI] 收到消息, message: " + message.toString());
        // 把 json 字符串转换为 Java 对象
        MessageRequest req = objectMapper.readValue(message.getPayload(), MessageRequest.class);
        switch (req.getType()) {
            case "message":
                User user = (User) session.getAttributes().get("user");
                if (user == null) {
                    System.out.println("当前用户不在线!");
                    return;
                }

                transferMessage(user, req);
                break;
            case "friendRequest":
                // 进行好友申请转发
                transferFriendRequest(req);
                break;
            case "acceptFriendRequest":
                // 接受好友请求
                transferAcceptRequest(req);
                break;
            default:
                System.out.println("[WebSocketAPI -> handleTextMessage] req.type 有误! " + message.getPayload());
                break;
        }
    }

    private void transferAcceptRequest(MessageRequest req) throws IOException {
        // req 中的 requestId 为要发送对象的 id
        WebSocketSession webSocketSession =
                onlineUserManager.getSession(req.getRequestId());

        System.out.println("[transferAcceptRequest] 接受好友请求, 发起方 id 为: " + req.getRequestId());
        MessageResponse response = new MessageResponse();
        response.setType("acceptFriendRequest");
        if (webSocketSession == null) {
            // 如果该用户未在线, 不发送
            return;
        }
        String respJson = objectMapper.writeValueAsString(response);

        webSocketSession.sendMessage(new TextMessage(respJson));
    }

    private void transferFriendRequest(MessageRequest req) throws IOException {
        // req 中的 receiver 为要发送对象的名字, 首先需要根据名字查找 id
        int toSendId = friendReqMapper.getUserIdByName(req.getReceiver());
        WebSocketSession webSocketSession =
                onlineUserManager.getSession(toSendId);

        System.out.println("[transferFriendRequest] 发送好友请求, 对方 id 为: " + toSendId);
        MessageResponse response = new MessageResponse();
        response.setType("friendRequest");
        if (webSocketSession == null) {
            // 如果该用户未在线, 不发送
            return;
        }
        String respJson = objectMapper.writeValueAsString(response);

        webSocketSession.sendMessage(new TextMessage(respJson));
    }

    private void transferMessage(User fromUser, MessageRequest req) throws IOException {
        // 构造响应对象
        MessageResponse response = new MessageResponse();

        response.setType("message");
        response.setFromId(fromUser.getUserId());
        response.setFromName(fromUser.getUsername());
        response.setSessionId(req.getSessionId());
        response.setContent(req.getContent());

        // 转成 json 字符串
        String respJson = objectMapper.writeValueAsString(response);
        System.out.println("[WebSocketAPI -> transferMessage] respJson: " + respJson);

        // 根据请求中的 sessionId 查询该会话中包含了哪些用户
        List<Friend> friends =
                messageSessionMapper.getFriendsBySessionId(req.getSessionId(), fromUser.getUserId());
        // 把自己加进去
        Friend myself = new Friend();
        myself.setFriendId(fromUser.getUserId());
        myself.setFriendName(myself.getFriendName());
        friends.add(myself);

        // 进行消息转发
        for (Friend friend : friends) {
            WebSocketSession webSocketSession =
                    onlineUserManager.getSession(friend.getFriendId());
            if (webSocketSession == null) {
                // 用户不在线
                continue;
            }
            webSocketSession.sendMessage(new TextMessage(respJson));
        }

        // 消息需要存入数据库中
        Message message = new Message();
        message.setFromId(fromUser.getUserId());
        message.setFromName(fromUser.getUsername());
        message.setSessionId(req.getSessionId());
        message.setContent(req.getContent());

        messageMapper.addMessage(message);
        // 修改当前会话的最后访问时间
        messageSessionMapper.updateLastTimeFromMessageSession(req.getSessionId());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("[WebSocketAPI] 连接异常 exception = " + exception.toString());
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("[WebSocketAPI] 连接关闭 status: " + status.toString());
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);
    }
}
